// 对一个对象实现响应式控制
const obj = {
  'a': 1,
  'b': 2,
  'c': 3
}

// 对属性值的操作函数
function getA() {
  console.log('a', obj.a)
}
function getB() {
  console.log('b', obj.b)
}
function getC() {
  console.log('c', obj.c)
}


// 实现一个observe方法，对对象的每一个属性进行监听
function observe(obj) {
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      let value = obj[key];
      let funcs = [];
      Object.defineProperty(obj, key, {
        get: function(){
          // 依赖收集，记录：添加需要使用该属性的函数    现在要考虑的问题就是如何知道当前的依赖函数 window.__fn__，见autoRun
          if (!funcs.includes(globalThis.__fn__)) {
            funcs.push(globalThis.__fn__);
          }
          return value;
        },
        set: function(val){
          value = val;
          // 派发更新，执行：运行依赖于该属性的函数
          funcs.forEach(fn => fn()); 
        },
      })
    }
  }
}

// autoRun 帮助执行依赖函数，将函数挂到window上就可以实现获取依赖函数--- 当我需要执行函数时，
function autoRun(fn) {
  globalThis.__fn__ = fn;
  // 在依赖函数执行之前，把依赖函数挂到window上，当首次执行依赖函数的时候，就能够从window对象上拿下来这个依赖并存放在依赖数组中（这就解决了如何确定当前属性被哪个函数所依赖）
  fn();
  globalThis.__fn__ = null;
}

// 测试
observe(obj);
console.log(obj)

// 首次执行收集依赖
autoRun(() => getA()); // 自动收集依赖于 `a` 的函数
autoRun(() => getB()); // 自动收集依赖于 `b` 的函数

// 触发派发更新
obj.a = 100; // 输出：a 100
obj.b = 200; // 输出：b 200